"""
数据保存服务
负责将AI分析结果保存到对应的数据库表
"""
from typing import Dict, Any, List, Optional, Type, Union
from sqlalchemy.orm import Session
from sqlalchemy import and_
import json
import logging
from datetime import datetime

from models.petition_record import (
    RegionalAnalysisResult,
    ComplaintTypeAnalysisResult,
    SentimentAnalysisResult,
    ComplianceAnalysisResult,
    DuplicateAnalysisResult,
    PetitionRecord
)
from models.analysis_task import AnalysisTask
from services.ai_service_factory import ServiceType, ServiceResponse
from core.logging_config import get_logger

logger = get_logger("data_save_service")


class DataSaveService:
    """数据保存服务"""

    def __init__(self):
        # 服务类型到数据库表的映射
        self.service_to_table_mapping = {
            ServiceType.INFORMATION_EXTRACTION: RegionalAnalysisResult,
            ServiceType.POLLUTION_TYPE_RECOGNITION: ComplaintTypeAnalysisResult,
            ServiceType.SENTIMENT_ANALYSIS: SentimentAnalysisResult,
            ServiceType.COMPLIANCE_CHECK: ComplianceAnalysisResult,
            ServiceType.DUPLICATE_DETECTION: DuplicateAnalysisResult,
            ServiceType.EXTRACT_INFO: RegionalAnalysisResult,
            ServiceType.LOCATION_ANALYSIS: RegionalAnalysisResult,
        }

        # 服务类型名称映射
        self.service_type_names = {
            ServiceType.INFORMATION_EXTRACTION: "信息抽取",
            ServiceType.POLLUTION_TYPE_RECOGNITION: "污染类型识别",
            ServiceType.SENTIMENT_ANALYSIS: "情感分析",
            ServiceType.COMPLIANCE_CHECK: "规范性检查",
            ServiceType.DUPLICATE_DETECTION: "重复检测",
            ServiceType.EXTRACT_INFO: "信息抽取",
            ServiceType.LOCATION_ANALYSIS: "位置分析",
        }

    def save_batch_results(self, db: Session, task_id: int, batch_results: Dict[str, Any]) -> Dict[str, Any]:
        """
        保存批量分析结果到数据库

        Args:
            db: 数据库会话
            task_id: 任务ID
            batch_results: 批量结果数据

        Returns:
            保存结果统计
        """
        try:
            results = batch_results.get("results", [])
            success_count = 0
            failed_count = 0

            for result in results:
                if isinstance(result, ServiceResponse):
                    if result.success:
                        save_result = self._save_single_result(db, task_id, result)
                        if save_result.get("success"):
                            success_count += 1
                        else:
                            failed_count += 1
                    else:
                        failed_count += 1
                else:
                    failed_count += 1

            logger.info(f"任务 {task_id} 数据保存完成: 成功 {success_count} 条, 失败 {failed_count} 条")

            return {
                "success": True,
                "success_count": success_count,
                "failed_count": failed_count,
                "total_count": len(results)
            }

        except Exception as e:
            logger.error(f"保存批量结果失败: {str(e)}")
            return {
                "success": False,
                "error": str(e),
                "success_count": 0,
                "failed_count": len(results) if "results" in locals() else 0
            }

    def _save_single_result(self, db: Session, task_id: int, result: ServiceResponse) -> Dict[str, Any]:
        """
        保存单个分析结果到数据库

        Args:
            db: 数据库会话
            task_id: 任务ID
            result: 单个服务响应结果

        Returns:
            保存结果
        """
        try:
            service_type = result.service_type
            data = result.data

            if not data or not data.get("petition_record_id"):
                logger.warning(f"缺少必要的数据字段: {result.request_id}")
                return {"success": False, "error": "缺少必要的数据字段"}

            # 获取对应的模型类
            model_class = self.service_to_table_mapping.get(service_type)
            if not model_class:
                logger.warning(f"不支持的服务类型: {service_type}")
                return {"success": False, "error": f"不支持的服务类型: {service_type}"}

            # 检查是否已存在相同记录
            existing_record = db.query(model_class).filter(
                and_(
                    model_class.task_id == task_id,
                    model_class.petition_record_id == data["petition_record_id"]
                )
            ).first()

            if existing_record:
                # 更新现有记录
                return self._update_existing_record(db, existing_record, data, service_type)
            else:
                # 创建新记录
                return self._create_new_record(db, model_class, task_id, data, service_type)

        except Exception as e:
            logger.error(f"保存单个结果失败: {str(e)}")
            return {"success": False, "error": str(e)}

    def _create_new_record(self, db: Session, model_class: Type, task_id: int,
                         data: Dict[str, Any], service_type: ServiceType) -> Dict[str, Any]:
        """创建新记录"""
        try:
            # 根据不同的服务类型创建对应的记录
            if service_type == ServiceType.INFORMATION_EXTRACTION:
                record = self._create_regional_analysis_record(task_id, data)
            elif service_type == ServiceType.POLLUTION_TYPE_RECOGNITION:
                record = self._create_complaint_type_record(task_id, data)
            elif service_type == ServiceType.SENTIMENT_ANALYSIS:
                record = self._create_sentiment_analysis_record(task_id, data)
            elif service_type == ServiceType.COMPLIANCE_CHECK:
                record = self._create_compliance_analysis_record(task_id, data)
            elif service_type == ServiceType.DUPLICATE_DETECTION:
                record = self._create_duplicate_analysis_record(task_id, data)
            else:
                record = self._create_regional_analysis_record(task_id, data)

            db.add(record)
            db.commit()

            logger.debug(f"创建新记录成功: {service_type} - {data.get('petition_record_id')}")
            return {"success": True}

        except Exception as e:
            db.rollback()
            logger.error(f"创建新记录失败: {str(e)}")
            return {"success": False, "error": str(e)}

    def _update_existing_record(self, db: Session, existing_record, data: Dict[str, Any],
                               service_type: ServiceType) -> Dict[str, Any]:
        """更新现有记录"""
        try:
            # 根据服务类型更新对应字段
            if service_type == ServiceType.INFORMATION_EXTRACTION:
                self._update_regional_analysis_record(existing_record, data)
            elif service_type == ServiceType.POLLUTION_TYPE_RECOGNITION:
                self._update_complaint_type_record(existing_record, data)
            elif service_type == ServiceType.SENTIMENT_ANALYSIS:
                self._update_sentiment_analysis_record(existing_record, data)
            elif service_type == ServiceType.COMPLIANCE_CHECK:
                self._update_compliance_analysis_record(existing_record, data)
            elif service_type == ServiceType.DUPLICATE_DETECTION:
                self._update_duplicate_analysis_record(existing_record, data)

            db.commit()

            logger.debug(f"更新现有记录成功: {service_type} - {data.get('petition_record_id')}")
            return {"success": True}

        except Exception as e:
            db.rollback()
            logger.error(f"更新现有记录失败: {str(e)}")
            return {"success": False, "error": str(e)}

    def _create_regional_analysis_record(self, task_id: int, data: Dict[str, Any]) -> RegionalAnalysisResult:
        """创建区域分析记录"""
        return RegionalAnalysisResult(
            petition_record_id=data["petition_record_id"],
            task_id=task_id,
            ccjbz=data.get("ccjbz", ""),
            tsr=data.get("tsr", ""),
            xfnr=data.get("xfnr", ""),
            ts_gk=data.get("ts_gk", ""),
            ts_xzq=data.get("ts_xzq", ""),
            ts_qxdw=data.get("ts_qxdw", ""),
            ts_dfnr=data.get("ts_dfnr", ""),
            ts_bz=data.get("ts_bz", ""),
            dzxx_tsdx=data.get("dzxx_tsdx", ""),
            dzxx_dx_words=",".join(data.get("dzxx_dx_words", [])),
            dzxx_tsdz=data.get("dzxx_tsdz", ""),
            dzxx_dz_words=",".join(data.get("dzxx_dz_words", "")),
            dzxx_ds=data.get("dzxx_ds", ""),
            dzxx_xzq=data.get("dzxx_xzq", ""),
            dzxx_jd=data.get("dzxx_jd", ""),
            dzxx_lng=data.get("dzxx_lng", ""),
            dzxx_lat=data.get("dzxx_lat", ""),
            cfxs_bh=data.get("cfxs_bh", ""),
            cfxs_gl=data.get("cfxs_gl", "")
        )

    def _create_complaint_type_record(self, task_id: int, data: Dict[str, Any]) -> ComplaintTypeAnalysisResult:
        """创建投诉类型分析记录"""
        return ComplaintTypeAnalysisResult(
            petition_record_id=data["petition_record_id"],
            task_id=task_id,
            xfnr=data.get("xfnr", ""),
            dzxx_tsdx=data.get("dzxx_tsdx", ""),
            dzxx_tsdz=data.get("dzxx_tsdz", ""),
            dzxx_xzq=data.get("dzxx_xzq", ""),
            dzxx_jd=data.get("dzxx_jd", ""),
            dzxx_lng=data.get("dzxx_lng", ""),
            dzxx_lat=data.get("dzxx_lat", ""),
            tslx_yj=data.get("tslx_yj", ""),
            tslx_yjyj=data.get("tslx_yjyj", ""),
            tslx_rj=data.get("tslx_rj", ""),
            tslx_rjyj=data.get("tslx_rjyj", ""),
            tslx_sj=data.get("tslx_sj", ""),
            tslx_sjyj=data.get("tslx_sjyj", ""),
            tslx_rj_zxd=data.get("tslx_rj_zxd", ""),
            tslx_sj_zxd=data.get("tslx_sj_zxd", "")
        )

    def _create_sentiment_analysis_record(self, task_id: int, data: Dict[str, Any]) -> SentimentAnalysisResult:
        """创建情感分析记录"""
        return SentimentAnalysisResult(
            petition_record_id=data["petition_record_id"],
            task_id=task_id,
            xfnr=data.get("xfnr", ""),
            dzxx_tsdx=data.get("dzxx_tsdx", ""),
            dzxx_tsdz=data.get("dzxx_tsdz", ""),
            dzxx_xzq=data.get("dzxx_xzq", ""),
            dzxx_jd=data.get("dzxx_jd", ""),
            dzxx_lng=data.get("dzxx_lng", ""),
            dzxx_lat=data.get("dzxx_lat", ""),
            qgfx_lx=data.get("qgfx_lx", ""),
            qgfx_pdly=data.get("qgfx_pdly", ""),
            qgfx_zy=data.get("qgfx_zy", ""),
            qgfx_gjc=data.get("qgfx_gjc", "")
        )

    def _create_compliance_analysis_record(self, task_id: int, data: Dict[str, Any]) -> ComplianceAnalysisResult:
        """创建规范性分析记录"""
        return ComplianceAnalysisResult(
            petition_record_id=data["petition_record_id"],
            task_id=task_id,
            xfnr=data.get("xfnr", ""),
            ts_qxdw=data.get("ts_qxdw", ""),
            dzxx_tsdx=data.get("dzxx_tsdx", ""),
            dzxx_tsdz=data.get("dzxx_tsdz", ""),
            dzxx_xzq=data.get("dzxx_xzq", ""),
            dzxx_jd=data.get("dzxx_jd", ""),
            dzxx_lng=data.get("dzxx_lng", ""),
            dzxx_lat=data.get("dzxx_lat", ""),
            gffx_dfnr=data.get("gffx_dfnr", ""),
            gffx_zt=data.get("gffx_zt", ""),
            gffx_pdly=data.get("gffx_pdly", "")
        )

    def _create_duplicate_analysis_record(self, task_id: int, data: Dict[str, Any]) -> DuplicateAnalysisResult:
        """创建重复分析记录"""
        return DuplicateAnalysisResult(
            task_id=task_id,
            bh=data.get("bh", ""),
            cfbh=data.get("cfbh", ""),
            xfxh=data.get("xfxh", "")
        )

    def _update_regional_analysis_record(self, record: RegionalAnalysisResult, data: Dict[str, Any]):
        """更新区域分析记录"""
        update_fields = ["ccjbz", "tsr", "xfnr", "ts_gk", "ts_xzq", "ts_qxdw", "ts_dfnr", "ts_bz",
                        "dzxx_tsdx", "dzxx_tsdz", "dzxx_ds", "dzxx_xzq", "dzxx_jd", "dzxx_lng", "dzxx_lat",
                        "cfxs_bh", "cfxs_gl", "dzxx_dx_words", "dzxx_dz_words"]

        for field in update_fields:
            if field in data:
                setattr(record, field, data[field])

    def _update_complaint_type_record(self, record: ComplaintTypeAnalysisResult, data: Dict[str, Any]):
        """更新投诉类型记录"""
        update_fields = ["xfnr", "dzxx_tsdx", "dzxx_tsdz", "dzxx_xzq", "dzxx_jd", "dzxx_lng", "dzxx_lat",
                        "tslx_yj", "tslx_yjyj", "tslx_rj", "tslx_rjyj", "tslx_sj", "tslx_sjyj",
                        "tslx_rj_zxd", "tslx_sj_zxd"]

        for field in update_fields:
            if field in data:
                setattr(record, field, data[field])

    def _update_sentiment_analysis_record(self, record: SentimentAnalysisResult, data: Dict[str, Any]):
        """更新情感分析记录"""
        update_fields = ["xfnr", "dzxx_tsdx", "dzxx_tsdz", "dzxx_xzq", "dzxx_jd", "dzxx_lng", "dzxx_lat",
                        "qgfx_lx", "qgfx_pdly", "qgfx_zy", "qgfx_gjc"]

        for field in update_fields:
            if field in data:
                setattr(record, field, data[field])

    def _update_compliance_analysis_record(self, record: ComplianceAnalysisResult, data: Dict[str, Any]):
        """更新规范性分析记录"""
        update_fields = ["xfnr", "dzxx_tsdx", "dzxx_tsdz", "dzxx_xzq", "dzxx_jd", "dzxx_lng", "dzxx_lat",
                        "gffx_dfnr", "gffx_zt", "gffx_pdly"]

        for field in update_fields:
            if field in data:
                setattr(record, field, data[field])

    def _update_duplicate_analysis_record(self, record: DuplicateAnalysisResult, data: Dict[str, Any]):
        """更新重复分析记录"""
        update_fields = ["bh", "cfbh", "xfxh"]

        for field in update_fields:
            if field in data:
                setattr(record, field, data[field])

    def get_task_statistics(self, db: Session, task_id: int) -> Dict[str, Any]:
        """获取任务统计信息"""
        try:
            stats = {}

            for service_type, model_class in self.service_to_table_mapping.items():
                count = db.query(model_class).filter(model_class.task_id == task_id).count()
                stats[self.service_type_names[service_type]] = count

            return {
                "success": True,
                "statistics": stats,
                "total": sum(stats.values())
            }

        except Exception as e:
            logger.error(f"获取任务统计信息失败: {str(e)}")
            return {"success": False, "error": str(e)}


# 全局数据保存服务实例
data_save_service = DataSaveService()